home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / apport / apport-gtk < prev    next >
Encoding:
Text File  |  2009-09-25  |  10.0 KB  |  265 lines

  1. #!/usr/bin/python
  2.  
  3. '''GTK Apport user interface. 
  4.  
  5. Copyright (C) 2007 Canonical Ltd.
  6. Author: Martin Pitt <martin.pitt@ubuntu.com>
  7.  
  8. This program is free software; you can redistribute it and/or modify it
  9. under the terms of the GNU General Public License as published by the
  10. Free Software Foundation; either version 2 of the License, or (at your
  11. option) any later version.  See http://www.gnu.org/copyleft/gpl.html for
  12. the full text of the license.
  13. '''
  14.  
  15. import os.path, sys, subprocess
  16. from gettext import gettext as _
  17. try:
  18.     import gobject, gtk, gtk.glade
  19.     import apport.ui
  20. except ImportError, e:
  21.     # this can happen while upgrading python packages
  22.     print >> sys.stderr, 'Could not import module, is a package upgrade in progress? Error:', e
  23.     sys.exit(1)
  24.  
  25. class GTKUserInterface(apport.ui.UserInterface):
  26.     '''GTK UserInterface.'''
  27.  
  28.     def w(self, widget):
  29.         '''Shortcut for getting a widget.'''
  30.  
  31.         return self.widgets.get_widget(widget)
  32.  
  33.     def __init__(self):
  34.         apport.ui.UserInterface.__init__(self)
  35.  
  36.         # load UI
  37.         gtk.window_set_default_icon_name("apport")
  38.         gtk.glade.textdomain(self.gettext_domain)
  39.         self.widgets = gtk.glade.XML(os.path.join(os.path.dirname(sys.argv[0]),
  40.             'apport-gtk.glade'))
  41.         self.widgets.signal_autoconnect(self)
  42.  
  43.         # initialize tree model and view
  44.         self.tree_model = gtk.TreeStore(gobject.TYPE_STRING)
  45.         self.w('treeview_reportdetails').set_model(self.tree_model)
  46.  
  47.         column = gtk.TreeViewColumn("Report", gtk.CellRendererText(), text=0)
  48.         self.w('treeview_reportdetails').append_column(column)
  49.  
  50.         # save the original strings of the dialogs (those which contain %s,
  51.         # which we replace later)
  52.         self.str_heading = self.w('label_heading').get_label()
  53.         self.str_heading_reopen = self.w('label_heading_reopen').get_label()
  54.         self.str_heading_package_error = self.w('label_heading_package_error').get_label()
  55.         self.str_heading_kernel_error = self.w('label_heading_kernel_error').get_label()
  56.         self.str_radio_complete = self.w('radiobutton_complete').get_label()
  57.         self.str_radio_reduced = self.w('radiobutton_reduced').get_label()
  58.  
  59.     #
  60.     # ui_* implementation of abstract UserInterface classes
  61.     #
  62.  
  63.     def ui_present_crash(self, desktop_entry): 
  64.         # adapt dialog heading and label appropriately
  65.         if desktop_entry:
  66.             heading = _('Sorry, %s closed unexpectedly') % desktop_entry.getName()
  67.         elif self.report.has_key('ExecutablePath'):
  68.             heading = _('Sorry, the program "%s" closed unexpectedly') % os.path.basename(self.report['ExecutablePath'])
  69.         else:
  70.             heading = _('Sorry, %s closed unexpectedly') % self.cur_package
  71.         if desktop_entry and self.report.has_key('ExecutablePath') and \
  72.         os.path.dirname(self.report['ExecutablePath']) in os.environ['PATH'].split(':') and \
  73.         subprocess.call(['pgrep', '-x',
  74.         os.path.basename(self.report['ExecutablePath']), 
  75.         '-u', str(os.geteuid())], stdout=subprocess.PIPE) != 0:
  76.             self.w('label_heading_reopen').set_markup(self.str_heading % heading)
  77.             d = self.w('dialog_crash_reopen')
  78.         bl_checkbox = self.w('checkbutton_blacklist_reopen')
  79.         else:
  80.             self.w('label_heading').set_markup(self.str_heading % heading)
  81.             d = self.w('dialog_crash')
  82.         bl_checkbox = self.w('checkbutton_blacklist')
  83.  
  84.         # show crash notification dialog
  85.         response = d.run()
  86.         d.hide()
  87.         while gtk.events_pending():
  88.             gtk.main_iteration(False)
  89.     blacklist = bl_checkbox.get_active()
  90.         if response == gtk.RESPONSE_YES:
  91.             return {'action': 'report', 'blacklist': blacklist}
  92.         elif response == gtk.RESPONSE_OK:
  93.             return {'action': 'restart', 'blacklist': blacklist}
  94.         else:
  95.             return {'action': 'cancel', 'blacklist': blacklist}
  96.  
  97.     def ui_present_package_error(self):
  98.     self.w('label_heading_package_error').set_markup(
  99.         self.str_heading_package_error % self.report['Package'])
  100.         response = self.w('dialog_package_error').run()
  101.         self.w('dialog_package_error').hide()
  102.         while gtk.events_pending():
  103.             gtk.main_iteration(False)
  104.         if response == gtk.RESPONSE_YES:
  105.             return 'report'
  106.         else:
  107.             return 'cancel'
  108.  
  109.     def ui_present_kernel_error(self):
  110.         message = _('Your system encountered a serious kernel problem.')
  111.         annotation = ''
  112.         if self.report.has_key('Annotation'):
  113.             annotation += self.report['Annotation'] + '\n\n'
  114.         annotation += _('You can help the developers to fix the problem by reporting it.')
  115.  
  116.         label = self.str_heading_kernel_error % (message, annotation)
  117.         self.w('label_heading_kernel_error').set_markup(label)
  118.  
  119.         response = self.w('dialog_kernel_error').run()
  120.         self.w('dialog_kernel_error').hide()
  121.         while gtk.events_pending():
  122.             gtk.main_iteration(False)
  123.         if response == gtk.RESPONSE_YES:
  124.             return 'report'
  125.         else:
  126.             return 'cancel'
  127.  
  128.     def ui_present_report_details(self):
  129.         # report contents in expander
  130.         self.tree_model.clear()
  131.         row = 0
  132.         for key in self.report:
  133.             keyiter = self.tree_model.insert_before(None, None)
  134.             self.tree_model.set_value(keyiter, 0, key)
  135.  
  136.             valiter = self.tree_model.insert_before(keyiter, None)
  137.             if not hasattr(self.report[key], 'gzipvalue') and \
  138.                 hasattr(self.report[key], 'isspace') and \
  139.                 not self.report._is_binary(self.report[key]):
  140.                 self.tree_model.set_value(valiter, 0, self.report[key])
  141.                 # expand the row if the value has less than 5 lines
  142.                 if len(filter(lambda c: c == '\n', self.report[key])) < 4:
  143.                     self.w('treeview_reportdetails').expand_row(row, False)
  144.             else:
  145.                 self.tree_model.set_value(valiter, 0, _('(binary data)'))
  146.  
  147.             row += 1
  148.  
  149.         # complete/reduced radio buttons
  150.         if self.report.has_key('CoreDump'):
  151.             self.w('radiobutton_complete').set_label(self.str_radio_complete % 
  152.                 self.format_filesize(self.get_complete_size()))
  153.             self.w('radiobutton_reduced').set_label(self.str_radio_reduced % 
  154.                 self.format_filesize(self.get_reduced_size()))
  155.             if self.report.has_useful_stacktrace():
  156.                 self.w('radiobutton_complete').set_sensitive(True)
  157.                 self.w('radiobutton_complete').show()
  158.                 self.w('radiobutton_reduced').show()
  159.             else:
  160.                 self.w('radiobutton_complete').set_sensitive(False)
  161.                 self.w('radiobutton_reduced').hide()
  162.         else:
  163.             self.w('radiobutton_complete').hide()
  164.             self.w('radiobutton_reduced').hide()
  165.  
  166.         response = self.w('dialog_bugreport').run()
  167.         self.w('dialog_bugreport').hide()
  168.         while gtk.events_pending():
  169.             gtk.main_iteration(False)
  170.  
  171.         if response == gtk.RESPONSE_OK:
  172.             if self.w('radiobutton_complete').get_active():
  173.                 return 'full'
  174.             else:
  175.                 return 'reduced'
  176.         else:
  177.             return 'cancel'
  178.  
  179.     def ui_info_message(self, title, text):
  180.         md = gtk.MessageDialog(type=gtk.MESSAGE_INFO,
  181.             buttons=gtk.BUTTONS_CLOSE, message_format=text)
  182.         md.set_title(title)
  183.         md.run()
  184.         md.hide()
  185.         while gtk.events_pending():
  186.             gtk.main_iteration(False)
  187.  
  188.     def ui_error_message(self, title, text):
  189.         md = gtk.MessageDialog(type=gtk.MESSAGE_ERROR,
  190.             buttons=gtk.BUTTONS_CLOSE, message_format=text)
  191.         md.set_title(title)
  192.         md.run()
  193.         md.hide()
  194.         while gtk.events_pending():
  195.             gtk.main_iteration(False)
  196.  
  197.     def ui_start_info_collection_progress(self):
  198.         self.w('progressbar_information_collection').set_fraction(0)
  199.         self.w('window_information_collection').show()
  200.         while gtk.events_pending():
  201.             gtk.main_iteration(False)
  202.  
  203.     def ui_pulse_info_collection_progress(self):
  204.         self.w('progressbar_information_collection').pulse()
  205.         while gtk.events_pending():
  206.             gtk.main_iteration(False)
  207.  
  208.     def ui_stop_info_collection_progress(self):
  209.         self.w('window_information_collection').hide()
  210.         while gtk.events_pending():
  211.             gtk.main_iteration(False)
  212.  
  213.     def ui_start_upload_progress(self):
  214.         '''Open a window with an definite progress bar, telling the user to
  215.         wait while debug information is being uploaded.'''
  216.  
  217.         self.w('progressbar_upload').set_fraction(0)
  218.         self.w('window_report_upload').show()
  219.         while gtk.events_pending():
  220.             gtk.main_iteration(False)
  221.  
  222.     def ui_set_upload_progress(self, progress):
  223.         '''Set the progress bar in the debug data upload progress
  224.         window to the given ratio (between 0 and 1, or None for indefinite
  225.         progress).
  226.         
  227.         This function is called every 100 ms.'''
  228.  
  229.         if progress:
  230.             self.w('progressbar_upload').set_fraction(progress)
  231.         else:
  232.             self.w('progressbar_upload').set_pulse_step(0.1)
  233.             self.w('progressbar_upload').pulse()
  234.         while gtk.events_pending():
  235.             gtk.main_iteration(False)
  236.  
  237.     def ui_stop_upload_progress(self):
  238.         '''Close debug data upload progress window.'''
  239.  
  240.         self.w('window_report_upload').hide()
  241.         while gtk.events_pending():
  242.             gtk.main_iteration(False)
  243.  
  244.     #
  245.     # Event handlers
  246.     #
  247.  
  248.     def on_progress_window_close_event(self, widget, event=None):
  249.         self.w('window_information_collection').hide()
  250.         self.w('window_report_upload').hide()
  251.         sys.exit(0)
  252.         return True
  253.  
  254.     def on_expander_details_activate(self, widget):
  255.         # signal is sent before actually expanding/collapsing, thus this
  256.         # requires negation
  257.         self.w('dialog_bugreport').set_resizable(not self.w('expander_details').get_expanded())
  258.         while gtk.events_pending():
  259.             gtk.main_iteration(False)
  260.         return True
  261.  
  262. if __name__ == '__main__':
  263.     app = GTKUserInterface()
  264.     app.run_argv()
  265.